package com.liuwei.spring.cloud.junit.threads;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

@Slf4j
public class VThreadJunit {

    public static void main(String[] args) throws InterruptedException {
        String javaFullVersion = System.getProperty("java.version");
        log.info("Java version: {}", javaFullVersion);
        VThreadJunit instance = new VThreadJunit();
        instance.executors();
        instance.threads();
        new CountDownLatch(1).await();
    }

    private void executors() throws InterruptedException {
        // 虚拟线程池（每个任务一个虚拟线程，适合 I/O 密集型）
        // Java 21/22 版本中 newVirtualThreadPerTaskExecutor() 的默认名称初始化逻辑 bug—— 虚拟线程启动后，getName() 可能返回空字符串（Java 23+ 已修复此问题）
        //ExecutorService virtualThreadPool = Executors.newVirtualThreadPerTaskExecutor();
        ThreadFactory virtualThreadFactory = new ThreadFactory() {
            private final AtomicLong threadId = new AtomicLong(1); // 自增序号，避免名称重复
            @Override
            public Thread newThread(Runnable task) {
                // 显式设置线程名称：前缀 + 自增序号
                return Thread.ofVirtual()
                        .name("VirtualThread-" + threadId.getAndIncrement())
                        .unstarted(task);
            }
        };
        ExecutorService virtualThreadPool = Executors.newThreadPerTaskExecutor(virtualThreadFactory);

        // CompletableFuture 指定虚拟线程池
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            // I/O 密集型任务（如 HTTP 调用、数据库查询）
            try {
                Thread t = Thread.currentThread();
                long id = t.getId();
                String name = t.getName();
                boolean isVirtual = t.isVirtual();
                Thread.State state = t.getState();
                log.info("Thread id:{},name:{},isVirtual:{},state:{}", id, name, isVirtual,state.name());
                // 模拟 I/O 阻塞（如网络请求等待）
                Thread.sleep(1000);
                log.info("this is a virtual thread");
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                return "任务中断";
            }
            return "I/O 任务完成";
        }, virtualThreadPool);

        // 处理结果
        future.thenAccept(result -> log.info(result));

        // 关闭虚拟线程池（会等待所有虚拟线程完成）
        virtualThreadPool.shutdown();
    }

    private void threads() throws InterruptedException {
        ThreadFactory threadFactory = new VirtualThreadFactory();
        ThreadPoolExecutor virtualThreadPool = new ThreadPoolExecutor(
                10, // 核心线程数
                100, // 最大线程数（限流）
                60, TimeUnit.SECONDS, // 空闲线程存活时间（兼容用）
                new ArrayBlockingQueue<>(1000), // 任务队列（缓冲）
                threadFactory, // 虚拟线程工厂
                new ThreadPoolExecutor.AbortPolicy() // 拒绝策略
        );

        // CompletableFuture 指定虚拟线程池
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            // I/O 密集型任务（如 HTTP 调用、数据库查询）
            try {
                Thread t = Thread.currentThread();
                long id = t.getId();
                String name = t.getName();
                boolean isVirtual = t.isVirtual();
                Thread.State state = t.getState();
                log.info("Thread id:{},name:{},isVirtual:{},state:{}", id, name, isVirtual,state.name());
                // 模拟 I/O 阻塞（如网络请求等待）
                Thread.sleep(1000);
                log.info("this is a virtual thread");
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                return "任务中断";
            }
            return "I/O 任务完成";
        }, virtualThreadPool);

        // 处理结果
        future.thenAccept(result -> log.info(result));

        // 关闭虚拟线程池（会等待所有虚拟线程完成）
        virtualThreadPool.shutdown();
    }


    /**
     * 线程工厂
     */
    private static class VirtualThreadFactory implements ThreadFactory {
        /**
         * 初始化线程名称时使用
         * 提供原子操作的Integer，线程安全的
         * AtomicInteger可以在并发情况下达到原子化更新，避免使用了synchronized，而且性能非常高。
         */
        private final AtomicInteger poolNumber = new AtomicInteger(1);
        /**
         * 指定当前线程的线程组，未指定时线程组为创建该线程所属的线程组
         */
        private final ThreadGroup group;
        /**
         * 构建线程实体时使用
         * 提供原子操作的Integer，线程安全的
         * AtomicInteger可以在并发情况下达到原子化更新，避免使用了synchronized，而且性能非常高。
         */
        private final AtomicInteger threadNumber = new AtomicInteger(1);
        /**
         * 线程名称
         */
        private final String namePrefix;

        VirtualThreadFactory() {
            group =  Thread.currentThread().getThreadGroup();
            namePrefix = "VirtualThread";
        }

        @Override
        public Thread newThread(Runnable runnable) {
            //Thread thread = new Thread(group, runnable, namePrefix + threadNumber.getAndIncrement(), 0);
            // 构建虚拟线程（Thread.ofVirtual() 是虚拟线程专属构建器）
            Thread thread = Thread.ofVirtual()
                    .name(namePrefix + "-" + threadNumber.getAndIncrement()) // 自定义名称（如：User-VirtualThread-1）
                    //.uncaughtExceptionHandler(exceptionHandler) // 绑定异常处理器
                    .unstarted(runnable); // 仅创建线程，不启动（线程池会自动启动）
            // 设置优先级为默认的
            if (thread.getPriority() != Thread.NORM_PRIORITY) {
                thread.setPriority(Thread.NORM_PRIORITY);
            }
            return thread;
        }
    }
}
